/**
 * 表达式计算和格式化工具函数
 */

import { calculateConstantValue } from './canvasUtils';

/**
 * 根据常量名获取常量值
 * @param {string} name - 常量名称
 * @param {Array} constants - 常量数组
 * @param {Array} points - 点数组
 * @returns {number|null} 常量值或null
 */
export function getConstantValueByName(name, constants, points) {
  const constant = constants.find(c => c.name === name);
  if (!constant) return null;
  const value = calculateConstantValue(constant, points, constants);
  return parseFloat(value);
}

/**
 * 格式化常量名称（用于非React环境）
 * @param {Object} constant - 常量对象
 * @returns {string} 格式化后的名称
 */
export function formatConstantNameText(constant) {
  if (constant.type === 'area') {
    const content = constant.name.replace(/^[Ss]+/g, '');
    return `S_${content}`;
  }
  return constant.name;
}

/**
 * 计算点在线段上的投影和比例
 * @param {Object} point - 点坐标 {x, y}
 * @param {Object} lineStart - 线段起点 {x, y}
 * @param {Object} lineEnd - 线段终点 {x, y}
 * @returns {Object} {x, y, t} - 投影点坐标和比例(0-1)
 */
export function projectPointOnLine(point, lineStart, lineEnd) {
  const dx = lineEnd.x - lineStart.x;
  const dy = lineEnd.y - lineStart.y;
  const lengthSquared = dx * dx + dy * dy;
  
  if (lengthSquared === 0) {
    return { x: lineStart.x, y: lineStart.y, t: 0 };
  }
  
  const t = Math.max(0, Math.min(1,
    ((point.x - lineStart.x) * dx + (point.y - lineStart.y) * dy) / lengthSquared
  ));
  
  return {
    x: lineStart.x + t * dx,
    y: lineStart.y + t * dy,
    t
  };
}

/**
 * 应用滑动点约束
 * 防止滑动点超出约束点
 * 约束的方向：从被约束点指向约束点
 * @param {Object} slidingPoint - 滑动点对象
 * @param {number} finalRatio - 滑动点在线段上的比例 (0-1)
 * @param {Array} slidingConstraints - 滑动点约束数组
 * @param {Array} points - 所有点的数组
 * @returns {number} 调整后的比例
 */
export function applySlidingConstraints(slidingPoint, finalRatio, slidingConstraints, points) {
  if (!slidingConstraints || slidingConstraints.length === 0) {
    return finalRatio;
  }

  // 获取该滑动点的所有约束
  const constraints = slidingConstraints.filter(c => c.slidingPointId === slidingPoint.id);
  if (constraints.length === 0) {
    return finalRatio;
  }

  // 获取滑动点所在的线段信息
  const { startPointId, endPointId } = slidingPoint.constrainedToLine;
  const startPoint = points.find(p => p.id === startPointId);
  const endPoint = points.find(p => p.id === endPointId);

  if (!startPoint || !endPoint) {
    return finalRatio;
  }

  let minRatio = 0;
  let maxRatio = 1;

  // 检查每个约束点
  for (const constraint of constraints) {
    const constraintPoint = points.find(p => p.id === constraint.constraintPointId);
    if (!constraintPoint) continue;

    // 计算约束点在线段上的投影比例
    const projection = projectPointOnLine(constraintPoint, startPoint, endPoint);
    const constraintRatio = projection.t;

    // 约束的方向：从被约束点指向约束点
    // 滑动点不能越过约束点
    // 如果滑动点当前位置 < 约束点位置，则约束点是上界（maxRatio）
    // 如果滑动点当前位置 > 约束点位置，则约束点是下界（minRatio）
    const slidingPointRatio = slidingPoint.constrainedToLine.ratio;

    if (slidingPointRatio < constraintRatio) {
      // 滑动点在约束点左边，约束点是上界
      maxRatio = Math.min(maxRatio, constraintRatio);
    } else if (slidingPointRatio > constraintRatio) {
      // 滑动点在约束点右边，约束点是下界
      minRatio = Math.max(minRatio, constraintRatio);
    }
  }

  // 限制滑动点的比例在约束范围内
  return Math.max(minRatio, Math.min(maxRatio, finalRatio));
}

/**
 * 更新滑动点位置
 * @param {Array} points - 所有点的数组
 * @param {string} draggedPointId - 被拖动的点的ID（可选，用于优化）
 * @returns {Array} 更新后的点数组
 */
export function updateSlidingPoints(points) {
  // 简单粗暴的方法：更新所有有 constrainedToLine 的点
  // 不管是否与 draggedPointId 相关，这样确保所有约束点都被正确更新
  return points.map(point => {
    if (!point.constrainedToLine) return point;

    const { startPointId, endPointId, ratio } = point.constrainedToLine;
    const startPoint = points.find(p => p.id === startPointId);
    const endPoint = points.find(p => p.id === endPointId);

    if (startPoint && endPoint) {
      const newX = startPoint.x + ratio * (endPoint.x - startPoint.x);
      const newY = startPoint.y + ratio * (endPoint.y - startPoint.y);
      return { ...point, x: newX, y: newY };
    }

    return point;
  });
}

/**
 * 检查点移动是否违反拖动约束
 * @param {Object} point - 点对象
 * @param {Object} newPos - 新位置 {x, y}
 * @param {Array} dragConstraints - 拖动约束数组
 * @param {Array} lines - 所有线段
 * @param {Array} points - 所有点
 * @returns {Object} {x, y} - 调整后的位置
 */
export function applyDragConstraints(point, newPos, dragConstraints, lines, points) {
  if (!dragConstraints || dragConstraints.length === 0) {
    return newPos;
  }
  
  // 获取该点的所有约束
  const constraints = dragConstraints.filter(c => c.pointId === point.id);
  if (constraints.length === 0) {
    return newPos;
  }
  
  let adjustedPos = { ...newPos };
  const oldPos = { x: point.x, y: point.y };
  
  // 最小距离阈值（防止图形归零）
  const MIN_DISTANCE = 20; // 像素单位
  
  // 检查每个约束
  for (const constraint of constraints) {
    const line = lines.find(l => l.id === constraint.lineId);
    if (!line) continue;
    
    const lineStart = points.find(p => p.id === line.startPointId);
    const lineEnd = points.find(p => p.id === line.endPointId);
    if (!lineStart || !lineEnd) continue;
    
    // 计算线段的方向向量
    const dx = lineEnd.x - lineStart.x;
    const dy = lineEnd.y - lineStart.y;
    const lineLength = Math.sqrt(dx * dx + dy * dy);
    if (lineLength === 0) continue;
    
    // 归一化方向向量和法向量
    const nx = -dy / lineLength; // 法向量 x
    const ny = dx / lineLength;  // 法向量 y
    
    // 计算旧位置和新位置到线段的有向距离（归一化）
    const oldDist = (oldPos.x - lineStart.x) * nx + (oldPos.y - lineStart.y) * ny;
    const newDist = (adjustedPos.x - lineStart.x) * nx + (adjustedPos.y - lineStart.y) * ny;
    
    // 确定点在线段的哪一侧
    const side = oldDist >= 0 ? 1 : -1;
    const absNewDist = Math.abs(newDist);
    
    // 如果新位置距离线段太近（小于最小距离）
    if (absNewDist < MIN_DISTANCE) {
      // 如果试图穿越线段（符号改变）
      if ((oldDist >= 0 && newDist < 0) || (oldDist <= 0 && newDist > 0)) {
        // 阻止穿越，保持在原来那一侧的最小距离处
        const t = ((adjustedPos.x - lineStart.x) * dx + (adjustedPos.y - lineStart.y) * dy) / (lineLength * lineLength);
        const projX = lineStart.x + t * dx;
        const projY = lineStart.y + t * dy;
        
        adjustedPos.x = projX + nx * side * MIN_DISTANCE;
        adjustedPos.y = projY + ny * side * MIN_DISTANCE;
      } else {
        // 同侧但距离不足，推回到最小距离
        const t = ((adjustedPos.x - lineStart.x) * dx + (adjustedPos.y - lineStart.y) * dy) / (lineLength * lineLength);
        const projX = lineStart.x + t * dx;
        const projY = lineStart.y + t * dy;
        
        adjustedPos.x = projX + nx * side * MIN_DISTANCE;
        adjustedPos.y = projY + ny * side * MIN_DISTANCE;
      }
    } else if ((oldDist >= 0 && newDist < 0) || (oldDist <= 0 && newDist > 0)) {
      // 距离足够但试图穿越，阻止穿越
      const t = ((adjustedPos.x - lineStart.x) * dx + (adjustedPos.y - lineStart.y) * dy) / (lineLength * lineLength);
      const projX = lineStart.x + t * dx;
      const projY = lineStart.y + t * dy;
      
      adjustedPos.x = projX + nx * side * MIN_DISTANCE;
      adjustedPos.y = projY + ny * side * MIN_DISTANCE;
    }
  }
  
  return adjustedPos;
}

/**
 * 获取画布坐标（考虑DPI缩放）
 * @param {MouseEvent|TouchEvent} e - 事件对象
 * @param {HTMLCanvasElement} canvas - Canvas元素
 * @returns {Object} {x, y} - 画布坐标
 */
export function getCanvasCoordinates(e, canvas) {
  const rect = canvas.getBoundingClientRect();
  const scaleX = canvas.width / rect.width;
  const scaleY = canvas.height / rect.height;
  
  // 处理触摸事件
  const clientX = e.touches ? e.touches[0].clientX : e.clientX;
  const clientY = e.touches ? e.touches[0].clientY : e.clientY;
  
  const x = (clientX - rect.left) * scaleX;
  const y = (clientY - rect.top) * scaleY;
  
  return { x, y };
}

/**
 * 更新所有垂足点的位置
 * @param {Array} points - 所有点的数组
 * @param {Array} perpendiculars - 垂线数组
 * @param {string} draggedPointId - 被拖动的点的ID（可选，用于优化）
 * @returns {Array} 更新后的点数组
 */
export function updatePerpendicularFootPoints(points, perpendiculars, draggedPointId = null) {
  if (!perpendiculars || perpendiculars.length === 0) {
    return points;
  }
  
  let updatedPoints = [...points];
  
  perpendiculars.forEach(perp => {
    if (!perp.footPointId) return;
    
    // 如果提供了draggedPointId，只更新相关的垂足点
    if (draggedPointId) {
      const isRelated = 
        perp.fromPointId === draggedPointId ||
        perp.toLineStartId === draggedPointId ||
        perp.toLineEndId === draggedPointId;
      
      if (!isRelated) return;
    }
    
    const fromPoint = updatedPoints.find(p => p.id === perp.fromPointId);
    const lineStart = updatedPoints.find(p => p.id === perp.toLineStartId);
    const lineEnd = updatedPoints.find(p => p.id === perp.toLineEndId);
    
    if (!fromPoint || !lineStart || !lineEnd) return;
    
    // 计算垂足位置（不限制在线段内）
    const dx = lineEnd.x - lineStart.x;
    const dy = lineEnd.y - lineStart.y;
    const lengthSquared = dx * dx + dy * dy;
    
    if (lengthSquared === 0) return;
    
    // 计算投影参数 t（不限制范围）
    const t = ((fromPoint.x - lineStart.x) * dx + (fromPoint.y - lineStart.y) * dy) / lengthSquared;
    
    const footX = lineStart.x + t * dx;
    const footY = lineStart.y + t * dy;
    
    // 更新垂足点
    updatedPoints = updatedPoints.map(p =>
      p.id === perp.footPointId ? {
        ...p,
        x: footX,
        y: footY,
        constrainedToLine: {
          ...p.constrainedToLine,
          ratio: t  // 不限制 ratio，允许超出线段范围
        }
      } : p
    );
  });
  
  return updatedPoints;
}

/**
 * 预处理表达式：插入隐式乘号（支持ab表示a*b）
 * @param {Array} eq - 表达式部分数组
 * @returns {Array} 处理后的表达式
 */
function preprocessEquation(eq) {
  const result = [];
  
  for (let i = 0; i < eq.length; i++) {
    const current = eq[i];
    const prev = i > 0 ? eq[i - 1] : null;
    
    // 添加当前元素之前，检查是否需要插入隐式乘号
    if (prev && shouldInsertMultiply(prev, current)) {
      result.push({ type: 'operator', value: '*' });
    }
    
    result.push(current);
  }
  
  return result;
}

/**
 * 判断两个相邻元素之间是否需要插入隐式乘号
 */
function shouldInsertMultiply(prev, current) {
  // 常量/数字后面跟常量/数字：插入*
  if ((prev.type === 'constant' || prev.type === 'number') && 
      (current.type === 'constant' || current.type === 'number')) {
    return true;
  }
  
  // 右括号后面跟常量/数字/左括号：插入*
  if (prev.type === 'bracket' && prev.value === ')') {
    if (current.type === 'constant' || current.type === 'number' || 
        (current.type === 'bracket' && current.value === '(')) {
      return true;
    }
  }
  
  // 常量/数字后面跟左括号：插入*
  if ((prev.type === 'constant' || prev.type === 'number') && 
      current.type === 'bracket' && current.value === '(') {
    return true;
  }
  
  // 平方后面跟常量/数字/左括号：插入*
  if (prev.type === 'operator' && prev.value === '^2') {
    if (current.type === 'constant' || current.type === 'number' || 
        (current.type === 'bracket' && current.value === '(')) {
      return true;
    }
  }
  
  return false;
}

/**
 * 计算单个表达式部分的值（支持 +, -, *, /, div, :, ^2, 括号, 隐式乘法）
 * @param {Array} eq - 表达式部分数组
 * @param {Function} getConstantValue - 获取常量值的函数
 * @returns {number|null} 计算结果
 */
export function evaluateEquation(eq, getConstantValue) {
  if (eq.length === 0) return null;
  
  // 预处理：插入隐式乘号
  eq = preprocessEquation(eq);
  
  // 单个常量或数字
  if (eq.length === 1) {
    if (eq[0].type === 'constant') {
      return getConstantValue(eq[0].name);
    } else if (eq[0].type === 'number') {
      return eq[0].value;
    }
    return null;
  }
  
  // 构建tokens，同时处理括号
  const tokens = [];
  let i = 0;
  
  while (i < eq.length) {
    const part = eq[i];
    
    if (part.type === 'bracket' && part.value === '(') {
      // 找到匹配的右括号
      let depth = 1;
      let j = i + 1;
      while (j < eq.length && depth > 0) {
        if (eq[j].type === 'bracket') {
          if (eq[j].value === '(') depth++;
          else if (eq[j].value === ')') depth--;
        }
        j++;
      }
      
      if (depth !== 0) return null; // 括号不匹配
      
      // 递归计算括号内的表达式
      const innerExpr = eq.slice(i + 1, j - 1);
      const innerValue = evaluateEquation(innerExpr, getConstantValue);
      if (innerValue === null) return null;
      
      tokens.push({ type: 'value', value: innerValue });
      i = j;
    } else if (part.type === 'constant') {
      const value = getConstantValue(part.name);
      if (value === null || isNaN(value)) return null;
      tokens.push({ type: 'value', value });
      i++;
    } else if (part.type === 'number') {
      tokens.push({ type: 'value', value: part.value });
      i++;
    } else if (part.type === 'operator') {
      tokens.push({ type: 'op', value: part.value });
      i++;
    } else {
      i++;
    }
  }
  
  // 第一步：处理平方（^2）
  i = 0;
  while (i < tokens.length) {
    if (i < tokens.length - 1 && tokens[i].type === 'value' && tokens[i + 1].type === 'op' && tokens[i + 1].value === '^2') {
      const value = tokens[i].value;
      const result = value * value;
      tokens.splice(i, 2, { type: 'value', value: result });
    } else {
      i++;
    }
  }
  
  // 第二步：处理乘法、除法（/、div 和 :）
  i = 0;
  while (i < tokens.length) {
    if (i < tokens.length - 2 && tokens[i].type === 'value' && tokens[i + 1].type === 'op') {
      const op = tokens[i + 1].value;
      if (op === '*' || op === '/' || op === 'div' || op === ':') {
        const left = tokens[i].value;
        const right = tokens[i + 2].value;
        let result;
        if (op === '*') {
          result = left * right;
        } else { // '/', 'div' or ':'
          if (right === 0) return null;
          result = left / right;
        }
        tokens.splice(i, 3, { type: 'value', value: result });
      } else {
        i++;
      }
    } else {
      i++;
    }
  }
  
  // 第三步：处理加法和减法
  i = 0;
  while (i < tokens.length) {
    if (i < tokens.length - 2 && tokens[i].type === 'value' && tokens[i + 1].type === 'op') {
      const op = tokens[i + 1].value;
      if (op === '+' || op === '-') {
        const left = tokens[i].value;
        const right = tokens[i + 2].value;
        const result = op === '+' ? left + right : left - right;
        tokens.splice(i, 3, { type: 'value', value: result });
      } else {
        i++;
      }
    } else {
      i++;
    }
  }
  
  // 最后应该只剩下一个值
  if (tokens.length === 1 && tokens[0].type === 'value') {
    return tokens[0].value;
  }
  
  return null;
}

/**
 * 验证表达式等式是否成立
 * @param {Object} expression - 表达式对象
 * @param {Function} getConstantValue - 获取常量值的函数
 * @returns {boolean} 是否成立
 */
export function validateExpression(expression, getConstantValue) {
  try {
    const { parts } = expression;
    if (parts.length === 0) return false;
    
    // 检查最后一个部分的类型
    const lastPart = parts[parts.length - 1];
    const endsWithEqual = lastPart.type === 'operator' && lastPart.value === '=';
    
    const equations = []; // 分割成多个等式
    let currentEq = [];
    
    // 按等号分割
    parts.forEach(part => {
      if (part.type === 'operator' && part.value === '=') {
        if (currentEq.length > 0) {
          equations.push(currentEq);
          currentEq = [];
        }
      } else {
        currentEq.push(part);
      }
    });
    if (currentEq.length > 0) {
      equations.push(currentEq);
    }

    // 如果以等号结尾，只验证等号之前的部分
    if (endsWithEqual) {
      // 如果只有一个等式（等号左边），总是有效的（会自动计算结果）
      if (equations.length === 1) return true;
      
      // 最后一个等式为空（因为等号后面没有内容）
      const validResults = equations.slice(0, -1).map(eq => evaluateEquation(eq, getConstantValue)).filter(r => r !== null);
      if (validResults.length === 0) return false;
      
      // 如果有多个等式且都能计算出值，检查是否只有一个（例如 S1*S4=S2=，会有两个等式）
      if (validResults.length === 1) return true;
      
      // 如果有多个等式，检查它们是否相等（允许一定误差）
      const first = validResults[0];
      const ABSOLUTE_TOLERANCE = 1.0;
      const RELATIVE_TOLERANCE = 0.005;
      
      return validResults.every(r => {
        const absDiff = Math.abs(r - first);
        const relDiff = Math.abs(absDiff / first);
        return absDiff < ABSOLUTE_TOLERANCE || relDiff < RELATIVE_TOLERANCE;
      });
    }
    
    // 如果以常量或数字结尾，表达式已完成，需要验证所有等式
    // 计算每个等式的值
    const results = equations.map(eq => evaluateEquation(eq, getConstantValue));
    const validResults = results.filter(r => r !== null);
    
    if (validResults.length === 0) return false;
    
    // 单个值总是有效的
    if (validResults.length === 1) return true;

    // 检查是否所有值都相等（允许一定误差，考虑浮点计算精度）
    const first = validResults[0];
    // 使用相对误差和绝对误差的组合判断
    // 绝对误差：允许 1.0 的差异
    // 相对误差：允许 0.5% 的差异
    const ABSOLUTE_TOLERANCE = 1.0;
    const RELATIVE_TOLERANCE = 0.005;
    
    const allEqual = validResults.every(r => {
      const absDiff = Math.abs(r - first);
      const relDiff = Math.abs(absDiff / first);
      return absDiff < ABSOLUTE_TOLERANCE || relDiff < RELATIVE_TOLERANCE;
    });
    
    return allEqual;
  } catch {
    return false;
  }
}

/**
 * 计算表达式的值
 * @param {Object} expression - 表达式对象
 * @param {Function} getConstantValue - 获取常量值的函数
 * @returns {string|null} 计算结果字符串，如果表达式已完成则返回 null（不显示数值）
 */
export function calculateExpressionValue(expression, getConstantValue) {
  try {
    const { parts } = expression;
    if (parts.length === 0) return '-';
    
    // 检查最后一个部分的类型
    const lastPart = parts[parts.length - 1];
    const endsWithEqual = lastPart.type === 'operator' && lastPart.value === '=';
    
    // 如果以常量或数字结尾，表达式已完成，不需要显示计算结果
    if (!endsWithEqual) {
      return null;
    }
    
    // 如果以等号结尾，计算等号之前的值作为结果
    const equations = []; // 分割成多个等式
    let currentEq = [];
    
    // 按等号分割
    parts.forEach(part => {
      if (part.type === 'operator' && part.value === '=') {
        if (currentEq.length > 0) {
          equations.push(currentEq);
          currentEq = [];
        }
      } else {
        currentEq.push(part);
      }
    });
    if (currentEq.length > 0) {
      equations.push(currentEq);
    }
    
    // 最后一个等式为空（因为等号后面没有内容）
    // 如果只有一个等式，直接计算它的值
    if (equations.length === 1 && equations[0].length > 0) {
      const result = evaluateEquation(equations[0], getConstantValue);
      if (result === null) return '-';
      return result.toFixed(2);
    }
    
    const validResults = equations.slice(0, -1).map(eq => evaluateEquation(eq, getConstantValue)).filter(r => r !== null);
    if (validResults.length === 0) return '-';
    
    // 取第一个值作为结果（会显示在等号后面）
    const result = validResults[0];
    
    // 正常显示，保留两位小数
    return result.toFixed(2);
  } catch {
    return '-';
  }
}

/**
 * 解析表达式为结构化的渲染数据（用于渲染分式等复杂格式）
 * @param {Object} expression - 表达式对象
 * @param {Array} constants - 常量数组（用于判断是否为面积常量）
 * @returns {Array} 渲染元素数组
 */
export function parseExpressionForRender(expression, constants = []) {
  const elements = [];
  const parts = expression.parts;
  
  if (parts.length === 0) return elements;
  
  // 新的渲染逻辑：先识别所有分式，然后按顺序渲染
  let i = 0;
  
  while (i < parts.length) {
    const currentPart = parts[i];
    
    // 检查当前是否是 '/' 运算符（分式开始）
    if (currentPart.type === 'operator' && currentPart.value === '/') {
      // 这是一个分式，需要找到分子和分母
      // 分子：向前查找，包含所有 '*' 和 '/'，直到遇到 '+'、'-'、'=' 或开始
      // 分母：向后查找，包含所有 '*'，直到遇到 '+'、'-'、'='、'/' 或结束
      
      // 查找分子（向前）
      const numeratorParts = [];
      let numStart = i - 1;
      while (numStart >= 0) {
        const p = parts[numStart];
        // 遇到 '+'、'-'、'=' 时停止（这些运算符优先级低于 '/'）
        if (p.type === 'operator' && (p.value === '+' || p.value === '-' || p.value === '=')) {
          break;
        }
        numeratorParts.unshift(p); // 从前面插入，保持顺序
        numStart--;
      }
      
      // 查找分母（向后）
      const denominatorParts = [];
      let denomStart = i + 1;
      while (denomStart < parts.length) {
        const p = parts[denomStart];
        // 遇到 '+'、'-'、'='、'/' 时停止
        // 遇到 '/' 时停止，因为多个 '/' 应该被分别处理（如 A/B/C 应该是 (A/B)/C）
        if (p.type === 'operator' && (p.value === '+' || p.value === '-' || p.value === '=' || p.value === '/')) {
          break;
        }
        denominatorParts.push(p);
        denomStart++;
      }
      
      // 只有当分子和分母都有内容时才创建分式
      if (numeratorParts.length > 0 && denominatorParts.length > 0) {
        // 移除 elements 中已经添加的分子部分（避免重复显示）
        // 从后往前检查，移除与分子部分匹配的元素
        const numPartsToRemove = numeratorParts.length;
        let removedCount = 0;
        for (let j = elements.length - 1; j >= 0 && removedCount < numPartsToRemove; j--) {
          const elem = elements[j];
          // 检查元素是否匹配分子的对应部分
          const correspondingNumPart = numeratorParts[numeratorParts.length - 1 - removedCount];
          if (correspondingNumPart) {
            let isMatch = false;
            // 匹配常量
            if (elem.type === 'constant' && correspondingNumPart.type === 'constant' && elem.name === correspondingNumPart.name) {
              isMatch = true;
            }
            // 匹配数字
            else if (elem.type === 'number' && correspondingNumPart.type === 'number' && elem.value === correspondingNumPart.value) {
              isMatch = true;
            }
            // 匹配运算符（包括 *、/、+、- 等）
            else if (elem.type === 'operator' && correspondingNumPart.type === 'operator' && elem.value === correspondingNumPart.value) {
              isMatch = true;
            }
            // 匹配括号
            else if (elem.type === 'bracket' && correspondingNumPart.type === 'bracket' && elem.value === correspondingNumPart.value) {
              isMatch = true;
            }
            
            if (isMatch) {
              elements.splice(j, 1);
              removedCount++;
            } else {
              // 如果不匹配，停止移除
              break;
            }
          } else {
            break;
          }
        }
        
        elements.push({
          type: 'fraction',
          numerator: numeratorParts.map(p => convertPartForRender(p, constants)),
          denominator: denominatorParts.map(p => convertPartForRender(p, constants))
        });
        // 跳到分母后面
        i = denomStart;
        continue;
      }
    }
    
    // 普通元素（包括等号、'÷' 和 'div' 运算符等）
    elements.push(convertPartForRender(currentPart, constants));
    i++;
  }
  
  // 如果最后一个元素是等号，移除它（因为结果前会自动添加等号，避免重复）
  if (elements.length > 0 && elements[elements.length - 1].type === 'operator' && elements[elements.length - 1].value === '=') {
    elements.pop();
  }
  
  return elements;
}

/**
 * 转换单个表达式部分为渲染数据
 * @param {Object} part - 表达式部分
 * @param {Array} constants - 常量数组
 * @returns {Object} 渲染数据
 */
function convertPartForRender(part, constants) {
  if (part.type === 'constant') {
    const constant = constants.find(c => c.name === part.name);
    const isArea = constant && constant.type === 'area';
    return {
      type: 'constant',
      name: part.name,
      isArea,
      displayName: isArea ? part.name.replace(/^[Ss]+/g, '') : part.name
    };
  } else if (part.type === 'number') {
    return {
      type: 'number',
      value: part.value
    };
  } else if (part.type === 'operator') {
    const symbolMap = {
      '*': '×',
      'div': '÷',
      '÷': '÷',  // 支持 ÷ 符号
      '/': '÷',   // 如果不是分式，则显示为 ÷（但通常 '/' 会被解析为分式）
      '+': '+',
      '-': '−',
      '=': ' = ',
      ':': ' : ',  // 比值
      '^2': '²'
    };
    return {
      type: 'operator',
      value: part.value,
      symbol: symbolMap[part.value] || part.value
    };
  } else if (part.type === 'bracket') {
    return {
      type: 'bracket',
      value: part.value
    };
  }
  return part;
}

/**
 * 更新所有定点的位置（基于固定端点的偏移量）
 * @param {Array} points - 所有点的数组
 * @param {string} movedPointId - 被移动的点的ID（可选，用于优化）
 * @returns {Array} 更新后的点数组
 */
export function updateFixedPoints(points, movedPointId = null) {
  return points.map(point => {
    // 只处理定点
    if (!point.fixedToPoint) return point;
    
    // 找到锚点
    const anchorPoint = points.find(p => p.id === point.fixedToPoint.anchorPointId);
    if (!anchorPoint) return point;
    
    // 如果指定了movedPointId，只在锚点是被移动的点时才更新
    if (movedPointId && anchorPoint.id !== movedPointId) return point;
    
    // 根据锚点位置和偏移量计算定点的新位置
    return {
      ...point,
      x: anchorPoint.x + point.fixedToPoint.offsetX,
      y: anchorPoint.y + point.fixedToPoint.offsetY
    };
  });
}

/**
 * 获取调整后的常量值（考虑表达式约束）
 * @param {string} constantName - 常量名称
 * @param {string} rawValue - 原始计算值（字符串格式，如 "535.27"）
 * @param {Array} expressions - 表达式数组
 * @param {Function} getConstantValue - 获取常量值的函数
 * @returns {string} 调整后的值
 */
export function getAdjustedConstantValue(constantName, rawValue, expressions, getConstantValue) {
  if (!expressions || expressions.length === 0) {
    return rawValue;
  }
  
  // 检查该常量是否涉及任何表达式
  const involvedExpressions = expressions.filter(expr => 
    expr.parts.some(part => part.type === 'constant' && part.name === constantName)
  );
  
  if (involvedExpressions.length === 0) {
    return rawValue;
  }
  
  // 对于每个涉及的表达式，尝试计算"理想值"
  for (const expression of involvedExpressions) {
    // 验证表达式是否成立
    if (!validateExpression(expression, getConstantValue)) {
      continue; // 表达式不成立，跳过
    }
    
    // 表达式成立，尝试计算理想值
    const { parts } = expression;
    
    // 按等号分割表达式
    const equations = [];
    let currentEq = [];
    
    parts.forEach(part => {
      if (part.type === 'operator' && part.value === '=') {
        if (currentEq.length > 0) {
          equations.push(currentEq);
          currentEq = [];
        }
      } else {
        currentEq.push(part);
      }
    });
    if (currentEq.length > 0) {
      equations.push(currentEq);
    }
    
    // 找到包含目标常量的等式和不包含的等式
    const equationsWithTarget = [];
    const equationsWithoutTarget = [];
    
    equations.forEach(eq => {
      const hasTarget = eq.some(part => part.type === 'constant' && part.name === constantName);
      if (hasTarget) {
        equationsWithTarget.push(eq);
      } else {
        equationsWithoutTarget.push(eq);
      }
    });
    
    // 如果有不包含目标常量的等式，计算它们的值作为理想值
    if (equationsWithoutTarget.length > 0) {
      const idealValues = equationsWithoutTarget
        .map(eq => evaluateEquation(eq, getConstantValue))
        .filter(v => v !== null);
      
      if (idealValues.length > 0) {
        // 使用第一个有效的理想值
        const idealValue = idealValues[0];
        
        // 检查原始值和理想值的差异
        const rawNum = parseFloat(rawValue);
        if (!isNaN(rawNum)) {
          const ABSOLUTE_TOLERANCE = 1.0;
          const RELATIVE_TOLERANCE = 0.005;
          const absDiff = Math.abs(rawNum - idealValue);
          const relDiff = Math.abs(absDiff / idealValue);
          
          // 如果在误差范围内，返回理想值
          if (absDiff < ABSOLUTE_TOLERANCE || relDiff < RELATIVE_TOLERANCE) {
            // 根据原始值的格式决定返回格式
            if (rawValue.includes('°')) {
              return idealValue.toFixed(1) + '°';
            } else {
              // 保持与原始值相同的小数位数
              const decimalPlaces = (rawValue.split('.')[1] || '').replace(/[^\d]/g, '').length;
              return idealValue.toFixed(decimalPlaces);
            }
          }
        }
      }
    }
  }
  
  // 没有找到合适的调整值，返回原始值
  return rawValue;
}

/**
 * 对一组数值进行分组并取平均值（误差在容差内的值归为一组）
 * @param {Array<number>} values - 数值数组
 * @param {number} tolerance - 容差（默认1.0）
 * @returns {Map<number, number>} 原始值到调整后值的映射
 */
export function groupAndAverageValues(values, tolerance = 1.0) {
  const valueMap = new Map();
  const groups = [];
  
  // 过滤掉无效值
  const validValues = values.filter(v => v !== null && !isNaN(v) && isFinite(v));
  if (validValues.length === 0) return valueMap;
  
  // 对每个值，找到它应该属于的组
  validValues.forEach(value => {
    let foundGroup = false;
    
    // 检查是否可以加入现有组
    for (const group of groups) {
      // 检查与组内所有值的差异
      const allWithinTolerance = group.every(v => Math.abs(v - value) <= tolerance);
      if (allWithinTolerance) {
        group.push(value);
        foundGroup = true;
        break;
      }
    }
    
    // 如果没有找到合适的组，创建新组
    if (!foundGroup) {
      groups.push([value]);
    }
  });
  
  // 对每个组计算平均值，并建立映射
  groups.forEach(group => {
    const average = group.reduce((sum, val) => sum + val, 0) / group.length;
    group.forEach(value => {
      valueMap.set(value, average);
    });
  });
  
  return valueMap;
}

/**
 * 获取调整后的数值（考虑全局误差调整）
 * @param {number} value - 原始值
 * @param {Map<number, number>} valueMap - 值映射表
 * @param {number} decimalPlaces - 小数位数（默认2）
 * @returns {string} 格式化后的字符串
 */
export function getAdjustedDisplayValue(value, valueMap, decimalPlaces = 2) {
  if (value === null || isNaN(value) || !isFinite(value)) return '-';
  
  const adjustedValue = valueMap.has(value) ? valueMap.get(value) : value;
  return adjustedValue.toFixed(decimalPlaces);
}

